/**
 * @class   wosh::SystemError
 * @brief   The class holds information about a generic system error.
 *          SystemError may be easily raised using raise() method.
 *
 ****************************************************************************
 * @version $Id: SystemError.h 2863 2010-08-07 04:28:58Z alex $
 * @author  Alessandro Polo
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

#ifndef __WOSH_Core_SystemError_H__
 #define __WOSH_Core_SystemError_H__

 #include <core/MessageContent.h>
 #include <core/URI.h>

 
namespace wosh {

class Message;
class Object;
class LogContext;
template <class T> class DataFieldCollector;
template <class T> class IDataFieldWrapper;

class SystemError : public MessageContent
 {
	WOSH_SERIALIZABLE(wosh::SystemError)
	WOSH_COMPARE_RTTI(wosh::SystemError)

	public:
		enum ERROR_PRIORITY {
			UNKNOWN				= 0x00,
			INFO				= 0x01,
			WARNING				= 0x02,
			CRITICAL			= 0x03
		};

		enum FAULT_TYPE {
			FAULT_UNKNOWN		= 0x00, ///<
			FAULT_TRANSIENT		= 0x01, ///< occur once and disappear
			FAULT_INTERMITTENT	= 0x02, ///< 
			FAULT_PERMANENT		= 0x04  ///< service need to be repaired
		};

	public:
		/**
		 * @brief  Empty constructor.
		 */
		SystemError();
		/**
		 * @brief  Constructor with initializer(s), provided for convenience.
		 * @param [in] errorCode the code of the error be assigned
		 */
		SystemError( long errorCode );
		/**
		 * @brief  Constructor with initializer(s), provided for convenience.
		 * @param [in] errorCode the code of the error be assigned
		 * @param [in] description the description of the error
		 * @param [in] Priority the priority of the error
		 */
		SystemError( long errorCode, const std::string& description, ERROR_PRIORITY Priority = SystemError::INFO );
		/**
		 * @brief  Copy constructor.
		 * @param m [in] the source object to be copied
		 */
		SystemError(const SystemError& m);
		/**
		 * @brief  Empty destructor.
		 */
		virtual ~SystemError() { }


	public:
		/**
		 * @brief  Clear the object. Acquire a new ID.
		 */
		virtual void clear();

	public:
		static int64 raise( const Object* source, SystemError::ERROR_PRIORITY priority, long error_code, const std::string& method_name, LogContext* log = NULL );
		static int64 raise( const Object* source, LogContext& log, SystemError::ERROR_PRIORITY priority, long error_code, const std::string& method_name, const char* stringFormat, ... );

	public:
		static Message* createMessage( Object* object, long error_code, SystemError::ERROR_PRIORITY priority, const std::string& description );

		static const char* getPriorityAsString( SystemError::ERROR_PRIORITY priority );
		static const char* getFaultTypeAsString( SystemError::FAULT_TYPE fault_type );


/** @name Getters
 * @{
 ******************************************************************************/
	public:
		inline int64 getID() const							{ return this->uid; }
		inline int64 getTimeStamp() const					{ return this->timestamp; }
		inline ERROR_PRIORITY getPriority() const			{ return this->priority; }
		inline FAULT_TYPE getFaultType() const				{ return this->fault_type; }

		inline const URI& getSource() const			{ return this->source; }
		inline URI& getSource()						{ return this->source; }

		inline long getErrorCode() const					{ return this->error_code; }

		inline const std::string& getMethod() const			{ return this->method; }
		inline std::string& getMethod()						{ return this->method; }

		inline const std::string& getDescription() const	{ return this->description; }
		inline std::string& getDescription()				{ return this->description; }

		inline const std::string& getContext() const		{ return this->context; }
		inline std::string& getContext()					{ return this->context; }

		inline const std::string& getTips() const			{ return this->tips; }
		inline std::string& getTips()						{ return this->tips; }

		std::string getBrief( unsigned int max = 255 ) const;

		/**
		 * @brief  Get MessageContent::TYPE of this implementation: a SYSTEM
		 * @return MessageContent::SYSTEM
		 */
		inline MessageContent::TYPE getType() const			{ return MessageContent::SYSTEM; }

		static DataFieldCollector<SystemError>* getDataFields();
		static IDataFieldWrapper<SystemError>* getPrimaryKeyWrapper();

//@}
/** @name Setters
 * @{
 ******************************************************************************/
	public:
		inline void setID( int64 value )						{ this->uid = value; }
		inline void setTimestamp( int64 value )					{ this->timestamp = value; }
		inline void setPriority( SystemError::ERROR_PRIORITY value )	{ this->priority = value; }
		inline void setFaultType( SystemError::FAULT_TYPE value )		{ this->fault_type = value; }
		inline void setErrorCode( long value )					{ this->error_code = value; }
		inline void setMethod( const std::string& value )		{ this->method = value; }
		inline void setDescription( const std::string& value )	{ this->description = value; }
		inline void setContext( const std::string& value )		{ this->context = value; }
		inline void setTips( const std::string& value )			{ this->tips = value; }

//@}
/** @name Operators Overloading
 * @{
 ******************************************************************************/
	public:
		virtual SystemError& operator=(const SystemError& m);
		virtual bool operator==(const SystemError &other) const;
		virtual bool operator!=(const SystemError &other) const	{ return !(*this == other);  }
//@}
/** @name Serialization interface
 * @{
 ******************************************************************************/
	public:
		virtual std::string toString() const;
		virtual bool updateHash( DataHashContext* hash_context ) const;
//@}
	protected:
		int64 uid;					///< unique id
		int64 timestamp;			///< creation timestamp
		ERROR_PRIORITY priority;	///< priority (refer to LogLevel)
		FAULT_TYPE fault_type;		///< type of the fault
		URI source;					///< error's source

		long error_code;			///< identifier of the error
		std::string method;			///< method name
		std::string description;	///< human friendly description
		std::string context;		///< context of the log
		std::string tips;			///< tips to fix the error


}; // class def

}; // namespace wosh

#endif //__WOSH_Core_SystemError_H__
